#include "calibimgviewer.h"
#include <QFileDialog>
#include <QStringList>
#include <QHeaderView>
#include <QTableWidgetItem>
#include <QList>
#include <QFileInfo>
#include <iostream>
#include <qmath.h>

CalibImgViewer::CalibImgViewer(QWidget *parent)
    : QWidget(parent)
{
    m_BatchSaveCount = 0;
    initScene();
    initWindow();
}

CalibImgViewer::~CalibImgViewer()
{
    
}

void CalibImgViewer::initScene()
{
    captureScene = new QGraphicsScene;
    captureView = new QGraphicsView;
    captureView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
    captureView->setDragMode(QGraphicsView::RubberBandDrag);
    captureView->setOptimizationFlags(QGraphicsView::DontSavePainterState);
    captureView->setScene(captureScene);
    captureView->resize(640,480);
}

void CalibImgViewer::initWindow()
{
    sliderZoom = new QSlider(Qt::Vertical);
    sliderZoom->setMinimum(0);
    sliderZoom->setMaximum(500);
    sliderZoom->setValue(250);
    sliderZoom->setTickPosition(QSlider::TicksRight);
    sliderCams = new QSlider(Qt::Horizontal);
    sliderCams->setTickPosition(QSlider::TicksBelow);
    sliderCams->setMinimum(0);
    sliderCams->setMaximum(PFCMU::CAMS-1);
    sliderFrames = new QSlider(Qt::Horizontal);
    sliderFrames->setTickPosition(QSlider::TicksBelow);
    labelCams = new QLabel(tr("CAMS"));
    labelCurrentCam = new QLabel(tr("%1").arg(sliderCams->value()));
    labelFrames = new QLabel(tr("FRAMES"));
    labelMinTimeStamp = new QLabel(tr("Not Set"));
    labelMaxTimeStamp = new QLabel(tr("Not Set"));
    labelCurrentTimeStamp = new QLabel(tr("Not Set"));

    gbxFps = new QGroupBox(tr("Select Fps"));
    gbxFps->setFixedWidth(200);
    fpsHLayout = new QHBoxLayout();
    rdo25Fps = new QRadioButton(tr("25fps"));
    rdo100Fps = new QRadioButton(tr("100fps"));
    rdo25Fps->setChecked(true);
    fpsHLayout->addWidget(rdo25Fps);
    fpsHLayout->addWidget(rdo100Fps);
    fpsHLayout->addStretch(1);
    gbxFps->setLayout(fpsHLayout);
    setTimeStampInc();

    gbxBatchLoad = new QGroupBox(tr("Batch Load"));
    gbxBatchLoad->setFixedWidth(200);
    labelBatchFilePrefix = new QLabel(tr("Prefix"));
    txtBatchFilePrefix = new QLineEdit;
    labelBatchFileStart = new QLabel(tr("Start"));
    txtBatchFileStart = new QLineEdit;
    labelBatchFileEnd = new QLabel(tr("End"));
    txtBatchFileEnd = new QLineEdit;
    labelBatchFileSuffix = new QLabel(tr("Suffix"));
    txtBatchFileSuffix = new QLineEdit;
    buttonLoadBatchFiles = new QPushButton("Load Batch");
    batchLoadGLayout = new QGridLayout;
    batchLoadGLayout->addWidget(labelBatchFilePrefix,0,0);
    batchLoadGLayout->addWidget(txtBatchFilePrefix,0,1);
    batchLoadGLayout->addWidget(labelBatchFileStart,1,0);
    batchLoadGLayout->addWidget(txtBatchFileStart,1,1);
    batchLoadGLayout->addWidget(labelBatchFileEnd,2,0);
    batchLoadGLayout->addWidget(txtBatchFileEnd,2,1);
    batchLoadGLayout->addWidget(labelBatchFileSuffix,3,0);
    batchLoadGLayout->addWidget(txtBatchFileSuffix,3,1);
    batchLoadGLayout->addWidget(buttonLoadBatchFiles,4,1);
    gbxBatchLoad->setLayout(batchLoadGLayout);

    gbxBatchSave = new QGroupBox(tr("Batch Save"));
    gbxBatchSave->setFixedWidth(200);
    labelBatchSavePrefix = new QLabel(tr("Prefix"));
    txtBatchSavePrefix = new QLineEdit;
    labelBatchSaveStart = new QLabel(tr("Start"));
    txtBatchSaveStart = new QLineEdit;
    labelBatchSaveEnd = new QLabel(tr("End"));
    txtBatchSaveEnd = new QLineEdit;
    labelBatchSaveCount = new QLabel(tr("Count"));
    txtBatchSaveCount = new QLineEdit;
    txtBatchSaveCount->setEnabled(false);
    txtBatchSaveCount->setText(tr("%1").arg(m_BatchSaveCount));
    buttonSaveBatchFiles = new QPushButton("Save Batch");
    batchSaveGLayout = new QGridLayout;
    batchSaveGLayout->addWidget(labelBatchSavePrefix,0,0);
    batchSaveGLayout->addWidget(txtBatchSavePrefix,0,1);
    batchSaveGLayout->addWidget(labelBatchSaveStart,1,0);
    batchSaveGLayout->addWidget(txtBatchSaveStart,1,1);
    //batchSaveGLayout->addWidget(labelBatchSaveEnd,2,0);
    //batchSaveGLayout->addWidget(txtBatchSaveEnd,2,1);
    batchSaveGLayout->addWidget(labelBatchSaveCount,2,0);
    batchSaveGLayout->addWidget(txtBatchSaveCount,2,1);
    batchSaveGLayout->addWidget(buttonSaveBatchFiles,3,1);
    gbxBatchSave->setLayout(batchSaveGLayout);

    buttonAddFile = new QPushButton(tr("Add File"));
    buttonRemoveFile = new QPushButton(tr("Remove File"));
    buttonRefresh = new QPushButton(tr("Refresh View"));
    buttonSaveImg=new QPushButton(tr("Save Image"));
    txtImgBaseName=new QLineEdit();
    txtImgBaseName->setText("img");
    txtImgBaseName->setFixedWidth(90);
    txtImgSaveCount=new QLineEdit();
    txtImgSaveCount->setText("1");
    txtImgSaveCount->setFixedWidth(50);
    buttonAutoSaveImg=new QPushButton(tr("Auto Save"));

    fileList = new QTableWidget();
    fileList->setFixedWidth(200);
    fileList->setColumnCount(1);
    fileList->setHorizontalHeaderLabels(QStringList(tr("File Name")));
    fileList->horizontalHeader()->resizeSection(0,200);

    camsSpliterHLayout = new QHBoxLayout();
    camsSpliterHLayout->addWidget(labelCams);
    camsSpliterHLayout->addWidget(labelCurrentCam);
    camsSpliterHLayout->addWidget(sliderCams);

    framesSpliterHLayout = new QHBoxLayout();
    framesSpliterHLayout->addWidget(labelFrames);
    framesSpliterHLayout->addWidget(labelCurrentTimeStamp);
    framesSpliterHLayout->addWidget(labelMinTimeStamp);
    framesSpliterHLayout->addWidget(sliderFrames);
    framesSpliterHLayout->addWidget(labelMaxTimeStamp);

    buttonViewAll = new QPushButton(tr("All Files"));
    buttonViewAll->setCheckable(true);
    buttonViewAll->setChecked(true);
    buttonViewAll->setEnabled(false);
    buttonViewAll->setMaximumWidth(100);
    labelSingleView = new QLabel(tr("Not set"));
    playHLayout = new QHBoxLayout();
    playHLayout->addWidget(buttonViewAll);
    playHLayout->addWidget(labelSingleView);
    playHLayout->addSpacing(50);


    viewHLayout = new QHBoxLayout();
    viewHLayout->addWidget(captureView);
    viewHLayout->addWidget(sliderZoom);

    viewVLayout = new QVBoxLayout();
    viewVLayout->addLayout(playHLayout);
    viewVLayout->addLayout(viewHLayout);
    viewVLayout->addLayout(camsSpliterHLayout);
    viewVLayout->addLayout(framesSpliterHLayout);

    listVLayout = new QVBoxLayout();
    listVLayout->addWidget(fileList);
    listVLayout->addWidget(gbxFps);
    listVLayout->addWidget(gbxBatchLoad);
    listVLayout->addWidget(buttonAddFile);
    listVLayout->addWidget(buttonRemoveFile);
    listVLayout->addWidget(buttonRefresh);
    listVLayout->addWidget(gbxBatchSave);
    //listVLayout->addWidget(buttonSaveImg);

    saveImgHLayout=new QHBoxLayout();
    saveImgHLayout->addWidget(txtImgBaseName);
    saveImgHLayout->addWidget(txtImgSaveCount);
    //listVLayout->addLayout(saveImgHLayout);
    //listVLayout->addWidget(buttonAutoSaveImg);


    mainHLayout = new QHBoxLayout();
    mainHLayout->addLayout(viewVLayout);
    mainHLayout->addLayout(listVLayout);

    this->setLayout(mainHLayout);
    //this->setFixedWidth(720);
    //this->resize(720, 600);

    connect(buttonAddFile, SIGNAL(clicked()), SLOT(onAddFiles()));
    connect(buttonRemoveFile, SIGNAL(clicked()), SLOT(onRemoveFile()));
    connect(buttonRefresh, SIGNAL(clicked()), SLOT(onRefreshView()));
    connect(buttonSaveImg, SIGNAL(clicked()), SLOT(onSaveImg()));
    connect(buttonAutoSaveImg,SIGNAL(clicked()),SLOT(onAutoSaveImg()));
    connect(buttonLoadBatchFiles, SIGNAL(clicked()), SLOT(onLoadBatchFiles()));
    connect(buttonSaveBatchFiles,SIGNAL(clicked()),SLOT(onSaveBatchFiles()));
}





void CalibImgViewer::onAddFiles()
{
    QStringList filesListStr;
    filesListStr = QFileDialog::getOpenFileNames(this, tr("Select Captured Files"), tr("/home"));
    if(filesListStr.count()!=0)
    {
        for(int i=0;i<filesListStr.count();i++)
        {
            QTableWidgetItem *fileRow = new QTableWidgetItem(filesListStr.at(i));
            fileList->insertRow(fileList->rowCount());
            fileList->setItem(fileList->rowCount()-1, 0, fileRow);
        }
    }
}

void CalibImgViewer::onRemoveFile()
{
    QList<QTableWidgetItem *> selectedFiles = fileList->selectedItems();
    if(selectedFiles.count()!=0)
    {
        for(int i=0;i<selectedFiles.count();i++)
        {
            int rowNumber = selectedFiles.at(i)->row();
            if(rowNumber!=-1)
            {
                fileList->removeRow(rowNumber);
            }
        }
    }
}

void CalibImgViewer::onRefreshView()
{
    PFCMU::timestamp_t minTimeStamp;
    PFCMU::timestamp_t maxTimeStamp;
    if(fileList->rowCount()>0)
    {
        setTimeStampInc();
        disconnect(sliderFrames, SIGNAL(valueChanged(int)), this, SLOT(onFrameChanged(int)));
        captureScene->clear();
        QString str(fileList->item(0,0)->text());
        QFileInfo fi(str);
        if(fi.exists())
        {
            int width = 640;
            if(TIMESTAMPINC==4)
            {
                width = 640;
            }
            else
            {
                width = 320;
            }
            ImageItem *gii = new ImageItem(&str,width);
            minTimeStamp = gii->getMinTimeStamp();
            maxTimeStamp = gii->getMaxTimeStamp();
        }
        else
        {
            for(int i=1;i<fileList->rowCount();i++)
            {
                QString str(fileList->item(i,0)->text());
                QFileInfo fi(str);
                if(fi.exists())
                {
                    int width = 640;
                    if(TIMESTAMPINC==4)
                    {
                        width = 640;
                    }
                    else
                    {
                        width = 320;
                    }
                    ImageItem *gii = new ImageItem(&str,width);
                    minTimeStamp = gii->getMinTimeStamp();
                    maxTimeStamp = gii->getMaxTimeStamp();
                    i=fileList->rowCount();
                }
            }
        }
    }

    captureScene->clear();

    for(int i=0;i<fileList->rowCount();i++)
    {
        QString str(fileList->item(i,0)->text());
        QFileInfo fi(str);
        if(fi.exists())
        {
            ImageItem *gii = new ImageItem(&str);
            minTimeStamp = std::min(minTimeStamp, gii->getMinTimeStamp());
            maxTimeStamp = std::max(maxTimeStamp, gii->getMaxTimeStamp());
            int xpos = i%4;
            int ypos = i/4;
            gii->setPos(xpos * gii->getWidth(), ypos * gii->getHeight());
            connect(this, SIGNAL(initTimeStamp(PFCMU::timestamp_t)),
                    gii, SLOT(onInitTimeStamp(PFCMU::timestamp_t)));
            connect(this, SIGNAL(timeStampChanged(PFCMU::timestamp_t)),
                    gii, SLOT(onTimeStampUpdated(PFCMU::timestamp_t)));
            connect(this, SIGNAL(camChanged(int)),
                    gii, SLOT(onCamUpdated(int)));
            connect(gii, SIGNAL(switchToSingle(QString*)),
                    this, SLOT(onSwitchToSingle(QString*)));
            captureScene->addItem(gii);
        }
    }
    m_MinFileGroupTimeStamp = minTimeStamp;
    m_MaxFileGroupTimeStamp = maxTimeStamp;
    emit initTimeStamp(minTimeStamp);
    resetFrameSlider(m_MinFileGroupTimeStamp, m_MaxFileGroupTimeStamp);
    sliderZoom->setValue(250);
    connect(sliderZoom, SIGNAL(valueChanged(int)), SLOT(setupViewMatrix(int)));
    connect(sliderFrames, SIGNAL(valueChanged(int)), SLOT(onFrameChanged(int)));
    connect(sliderCams, SIGNAL(valueChanged(int)),SLOT(onCamsChanged(int)));
}

void CalibImgViewer::onSaveImg()
{
    QList<QGraphicsItem *> itemsInScene = captureScene->items();
    if(itemsInScene.count()==1)
    {
        ImageItem *gii = static_cast<ImageItem *>(itemsInScene.at(0));
        QFileDialog *fd = new QFileDialog(this);
        fd->setFileMode(QFileDialog::AnyFile);
        QString fileName;
        fd->setDirectory("/home/demo/captured");
        if(fd->exec()==QDialog::Accepted)
        {
            fileName = fd->selectedFiles().at(0);
        }
        gii->saveQImage(fileName);
    }
}

void CalibImgViewer::onAutoSaveImg()
{
    QList<QGraphicsItem *> itemsInScene = captureScene->items();
    if(itemsInScene.count()==1)
    {
        ImageItem *gii = static_cast<ImageItem *>(itemsInScene.at(0));
        QString fileBaseName="img";
        QString pathName="/home/demo/captured/imgs/";
        QString fileCount="1";
        if(txtImgBaseName->text()!="")
        {
            fileBaseName=txtImgBaseName->text();
        }
        if(txtImgSaveCount->text()!="")
        {
            fileCount=txtImgSaveCount->text();
        }
        QString fileName(pathName);
        fileName.append(fileBaseName);
        fileName.append(fileCount);
        fileName.append(".bmp");
        gii->saveQImage(fileName);
        //qDebug(fileName.toAscii());
        int count=fileCount.toInt();
        count++;
        txtImgSaveCount->setText(QString("%1").arg(count));


    }
}

void CalibImgViewer::onLoadBatchFiles()
{
    //TODO
    int startFile = txtBatchFileStart->text().toInt();
    int endFile = txtBatchFileEnd->text().toInt();
    for(int i=startFile;i<=endFile;i++)
    {
        QString filePath = tr("%1%2%3").
                arg(txtBatchFilePrefix->text()).
                arg(i,2,10,QChar('0')).
                arg(txtBatchFileSuffix->text());
        QTableWidgetItem *fileRow = new QTableWidgetItem(filePath);
        fileList->insertRow(fileList->rowCount());
        fileList->setItem(fileList->rowCount()-1,0,fileRow);
    }
}

void CalibImgViewer::onSaveBatchFiles()
{
    //TODO
    QString filePrefix(txtBatchSavePrefix->text());
    int countStart = txtBatchSaveStart->text().toInt();
    int totalImg = captureScene->items().count();
    QList<QGraphicsItem *> itemsInScene = captureScene->items();
    for(int i=0;i<totalImg;i++)
    {
        ImageItem *gii = static_cast<ImageItem *>(itemsInScene.at(i));
        if(gii->checked())
        {
            QString fileName = tr("%1%2/%3.bmp").
                    arg(filePrefix).
                    arg(countStart+i).
                    arg(m_BatchSaveCount);
            gii->saveQImage(fileName);
        }
    }
    m_BatchSaveCount++;
}

void CalibImgViewer::setupViewMatrix(int size)
{
    //TODO
    qreal scale = qPow(qreal(2),(size-250)/qreal(50));
    QMatrix matrix;
    matrix.scale(scale,scale);
    matrix.rotate(qreal(0));

    QList<QGraphicsItem *> itemsInScene = captureScene->items();
    int width = static_cast<ImageItem *>(itemsInScene.at(0))->getWidth();
    int viewWidth = captureView->width();
    int itemsInRow = viewWidth / (width * scale) + 1;
    if(itemsInRow>1)
    {
        itemsInRow--;
    }
    for(int i=0;i<itemsInScene.count();i++)
    {
        ImageItem *gii = static_cast<ImageItem *>(itemsInScene.at(i));
        int xpos = i%itemsInRow;
        int ypos = i/itemsInRow;
        gii->setPos(xpos * gii->getWidth(), ypos * gii->getHeight());
    }
    captureView->setMatrix(matrix);
}

void CalibImgViewer::resetFrameSlider(PFCMU::timestamp_t minValue, PFCMU::timestamp_t maxValue)
{
    sliderFrames->setMinimum(0);
    sliderFrames->setMaximum((maxValue-minValue)/TIMESTAMPINC);
    sliderFrames->setValue(sliderFrames->minimum());
    labelMinTimeStamp->setText(tr("%1").arg(minValue));
    labelMaxTimeStamp->setText(tr("%1").arg(maxValue));
    labelCurrentTimeStamp->setText(tr("%1").arg(minValue));
}

void CalibImgViewer::onFrameChanged(int value)
{
    labelCurrentTimeStamp->setText(tr("%1").arg(m_MinFileGroupTimeStamp+value*TIMESTAMPINC));
    emit timeStampChanged(m_MinFileGroupTimeStamp+value*TIMESTAMPINC);
}

void CalibImgViewer::onCamsChanged(int value)
{
    labelCurrentCam->setText(tr("%1").arg(sliderCams->value()));
    emit camChanged(sliderCams->value());
}


void CalibImgViewer::setTimeStampInc()
{
    if(rdo100Fps->isChecked())
        TIMESTAMPINC = 1;
    else
        TIMESTAMPINC = 4;
}
